<template>
  <div class="scroll" ref="scrollContainer">
    <div class="scroll-content" ref="scrollContent">
      <!-- 第一段内容 -->
      <div
        class="scroll-first items-center"
        ref="groupA"
        :style="{ transform: groupATransform }"
      >
        <slot name="cell" :list="groupAList" prefix="first"></slot>
      </div>
      <!-- 第二段内容 -->
      <div
        v-if="groupA && groupBList.length"
        class="scroll-second items-center"
        ref="groupB"
        :style="{ transform: groupBTransform }"
      >
        <slot name="cell" :list="groupBList" prefix="second"></slot>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick } from "vue";

const props = defineProps({
  // 数据源数组: 数据长度不能小于 8
  list: {
    type: Array,
    default: [],
  },
  // 默认循环
  loop: {
    type: Boolean,
    default: true,
  },
  // 初始滚动速度，单位：px/s
  speed: {
    type: Number,
    default: 100,
  },
  // 要加载的组件components路径
  slotPath: {
    type: String,
    default: "",
  },
});

// 模拟的中奖信息数据
let items = [];

// 默认一组至少有 4 个数据
let part = 4;

/**
 * @description: findSmallestDivisor(Math.floor(Math.random() * 9999));随机数为 ${randomNumber}，能整除它的最小数（不小于 3）为 ${smallestDivisor}
 * @param {*} num
 */
function findSmallestDivisor(num) {
  if (num < 2) {
    return null;
  }
  for (let i = Math.max(3, num > 3 ? 2 : 0); i <= num; i++) {
    if (num % i === 0) {
      return i;
    }
  }
  return num;
}

/**
 * @description: 数据源初始化
 * 1. 防止出现数据太少的情况
 * 2. 加载组件
 */
async function initDataSource() {
  // 1. 防止出现数据太少的情况
  if (props.list.length > 1) {
    if (props.list.length < 8) {
      items = props.list
        .concat(props.list)
        .concat(props.list)
        .concat(props.list)
        .concat(props.list)
        .concat(props.list)
        .concat(props.list)
        .concat(props.list);
    } else {
      items = JSON.parse(JSON.stringify(props.list));
    }
  } else {
    return console.error("infoScroll组件 list 属性:长度必须大于 1");
  }
  // 1.1 求出一组展示几个
  part = findSmallestDivisor(props.list.length);
  // console.log("part:", part);
}

await initDataSource();

// 将数据分为每组 5 个，共 20 组
const groups = Array.from({ length: props.list.length / part }, (_, i) =>
  items.slice(i * part, (i + 1) * part)
);

// console.log("groups:", groups);

// 引用
const scrollContainer = ref(null);
const scrollContent = ref(null);
const groupA = ref(null);
const groupB = ref(null);

const groupAList = ref(groups[0]);
const groupBList = ref(groups[1]);

let animationFrameId = null;

// 宽度变量
let groupAWidth = 0;
let groupBWidth = 0;

// 当前渲染了第几组数据; 索引
let currentPart = 1;

// A 的 left位置
const groupAleft = ref(0);

// B 的 left位置
const groupBleft = ref(0);

const groupATransform = computed(
  () => `translateX(${groupAleft.value || 0}px)`
);
const groupBTransform = computed(
  () => `translateX(${groupBleft.value || 0}px)`
);

// 开始滚动函数
const startScrolling = () => {
  const container = scrollContainer.value;
  const content = scrollContent.value;
  if (!container || !content) return;

  // 每帧滚动的像素数
  const pixelsToScroll = props.speed / 60;

  const step = () => {
    container.scrollLeft += pixelsToScroll;

    // 第一段滚动结束: 1. 偏移量 >= B 的开始位置  10 代表可调幅度 2. A 的开始位置小于 B 的开始位置
    if (
      container.scrollLeft >= groupBleft.value + 10 &&
      groupAleft.value < groupBleft.value
    ) {
      // 1. 改变 A 位置
      groupAleft.value = groupBleft.value + groupBWidth;
      console.log("重置 A 的位置", groupAleft.value);

      // 2. 重新赋值数据
      currentPart += 1;
      if (currentPart < groups.length) {
        groupAList.value = groups[currentPart];
      } else {
        currentPart = 0;
        groupAList.value = groups[currentPart];
      }
      // 3. 重新获取 A 的宽度
      setTimeout(() => {
        if (groupA.value) {
          const rect = groupA.value.getBoundingClientRect();
          console.log(rect, "重新获取 A 的宽度:", rect.width);
          groupAWidth = rect.width;
        }
      }, 2);
    }

    // 第二段滚动结束
    if (
      container.scrollLeft >= groupAleft.value + 10 &&
      groupBleft.value < groupAleft.value
    ) {
      // 1. 改变 B 位置
      groupBleft.value = groupAleft.value + groupAWidth;
      console.log("重置 B 的位置", groupBleft.value);
      // 2. 重新赋值数据
      currentPart += 1;
      if (currentPart < groups.length) {
        groupBList.value = groups[currentPart];
      } else {
        currentPart = 0;
        groupBList.value = groups[currentPart];
      }
      // 3. 重新获取 B 的宽度
      setTimeout(() => {
        if (groupB.value) {
          const rect = groupB.value.getBoundingClientRect();
          console.log(rect, "重新获取 B 的宽度:", rect.width);
          groupBWidth = rect.width;
        }
      }, 2);
    }

    animationFrameId = requestAnimationFrame(step);
  };

  animationFrameId = requestAnimationFrame(step);
};

// 组件挂载后
onMounted(async () => {
  await nextTick(); // 确保 DOM 已渲染
  if (groupA.value) {
    groupAWidth = groupA.value.offsetWidth;
    // 设置第一次 B 的位置
    groupBleft.value = groupA.value.offsetWidth;
    console.log("初始化 A 的宽度:", groupAWidth, "B 的位置", groupBleft.value);
  }
  await nextTick(); // 确保 DOM 已渲染
  if (groupB.value) {
    setTimeout(() => {
      groupBWidth = groupB.value.getBoundingClientRect().width;
      console.log(
        "初始化 B 的宽度:",
        groupBWidth,
        "A  下一次的位置",
        groupBleft.value + groupBWidth
      );
    }, 2);
    startScrolling();
  }
});

// 组件卸载前
onBeforeUnmount(() => {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }
});
</script>

<style scoped lang="scss">
.scroll {
  will-change: transform;
  width: 100vw;
  overflow-x: scroll;
  overflow-y: hidden;
  background-color: #f9f9f9;
  border: 1px solid red;
  position: relative;

  &-content {
    height: 50px;
    position: relative;
    width: 200000000000px;
  }

  &-first,
  &-second {
    position: absolute;
    will-change: transform; /* 提示浏览器优化 transform */
  }
}
</style>
